package com.jl.gongniu.service;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jl.api.CommonApi;
import com.jl.constants.SysConstants;
import com.jl.constants.UserRole;
import com.jl.enums.*;
import com.jl.exception.RRException;
import com.jl.gongniu.enums.Choice;
import com.jl.gongniu.mapper.GongNiuRecordMapper;
import com.jl.gongniu.mapper.GongNiuRoomMapper;
import com.jl.gongniu.model.CoalitionGongNiuRecord;
import com.jl.gongniu.model.CoalitionGongNiuRoom;
import com.jl.gongniu.model.GongNiuParam;
import com.jl.gongniu.model.GongNiuRoomUserBaseInfo;
import com.jl.gongniu.model.dto.*;
import com.jl.mapper.AuthMapper;
import com.jl.mapper.PercentageMapper;
import com.jl.mapper.RoomMapper;
import com.jl.model.*;
import com.jl.model.gongniu.enums.*;
import com.jl.model.req.RoomIntoReq;
import com.jl.model.resp.InteractionResp;
import com.jl.model.resp.ReviewResp;
import com.jl.model.resp.RoomInfoResp;
import com.jl.model.resp.VoiceResp;
import com.jl.model.socket.RoomDetail;
import com.jl.model.vo.UserVo;
import com.jl.service.GetUserInfoService;
import com.jl.service.RoomInfoService;
import com.jl.utils.CommonUtils;
import com.jl.utils.MySocketUtil;
import com.jl.utils.ObjectUtils;
import com.jl.utils.UserInfoContext;
import com.jl.utils.netty.JavaWebSocketClient;
import com.jl.utils.netty.JavaWebSocketFactory;
import com.jl.utils.niuniu.*;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.PropertyUtils;
import org.java_websocket.client.WebSocketClient;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Service
@Transactional
@Slf4j
public class GongNiuService implements CommonApi {

    private Integer coalitionId = 88888;
    @Resource
    private GetUserInfoService getUserInfoService;
    @Resource
    private RoomInfoService roomInfoService;
    @Resource
    private GongNiuRoomMapper gongNiuRoomMapper;
    @Resource
    private RoomMapper roomMapper;
    @Resource
    private GongNiuRecordMapper gongNiuRecordMapper;
    @Resource
    private PercentageMapper percentageMapper;
    @Resource
    private AuthMapper authMapper;
    @Resource
    private RedisTemplate<String,String> redisTemplate;

    @Override
    public Object getParam() {
        try {
            GongNiuParam gongNiuParam = CommonUtils.packParam(GongNiuParam.class, GameType.class, PeopleNumber.class, GameNumber.class, RoomRate.class,
                    GameBegin.class, Ante.class, AdvancedOptions.class,FlopRule.class);
            return gongNiuParam;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public Object createRoom(Object object) {
        UserVo user = UserInfoContext.getUser();
        User userInfo = new User();
        userInfo.setId(user.getId());
        BigDecimal coin = getUserInfoService.getUserRealTime(userInfo);
        GongNiuParamDto gongNiuParamDto = JSONObject.parseObject(JSONObject.toJSONString(object), GongNiuParamDto.class);
        if (!user.getUserRole().equals(UserRole.管理员.getValue())){ //如果不是管理员,判断是否有足够的游戏币
            if (gongNiuParamDto.getRoomRate().equals(RoomRate.type1.getId())){
                if (!RoomRate.compareTo(RoomRate.type1,coin)){
                    throw new RRException("501","玩家金币不足,无法支付");
                }
            }
        }
        CoalitionGongNiuRoom coalitionRoom = new CoalitionGongNiuRoom();
        BeanUtils.copyProperties(gongNiuParamDto,coalitionRoom);
        GongNiuRoomCreateResp gongNiuRoomCreateResp = new GongNiuRoomCreateResp();
        gongNiuRoomCreateResp.setPlay("暗牌玩法");
        try {
            CommonUtils.setParam(gongNiuParamDto,gongNiuRoomCreateResp);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (coalitionRoom.getId()!=null){ //编辑
            gongNiuRoomMapper.updateByPrimaryKeySelective(coalitionRoom);
        }else { //新增
//                coalitionRoom.setCreateTime(new Date());
//                gongNiuRoomMapper.insert(coalitionRoom);
            CoalitionRoom room = new CoalitionRoom();
            room.setCreateTime(new Date());
            room.setGameType("2");
            room.setCreateBy(user.getId());
            room.setStatus("1");
            if (coalitionRoom.getCoalitionId()==null){ //创建私人房间
                room.setPersonal("1");
                //扣除游戏币
                if (RoomRate.type1.getId().equals(gongNiuParamDto.getRoomRate())){
                    getUserInfoService.changeAccount(2,user.getId(),new BigDecimal(RoomRate.type1.getValue()));
                }
            }else {
                room.setPersonal("0");
            }
            roomMapper.insertUseGeneratedKeys(room);
            coalitionRoom.setCreateTime(new Date());
            coalitionRoom.setId(room.getId());
            if (gongNiuParamDto.getIntoCoin()==null){
                coalitionRoom.setIntoCoin(new BigDecimal(0));
            }
            gongNiuRoomMapper.insert(coalitionRoom);
            gongNiuRoomCreateResp.setId(room.getId());
        }
        roomInfoService.setRoomDetail(gongNiuParamDto);
        return gongNiuRoomCreateResp;
    }

    @Override
    public Object recordQuery() {
        UserVo user = UserInfoContext.getUser();
        List<GongNiuRecordDto> records = gongNiuRecordMapper.selectRecord(user.getId());
//        for (GongNiuRecordDto niuRecordDto : records) {
//            for (GongNiuRecordDetailDto detail : niuRecordDto.getDetails()) {
//                String desc = CommonUtils.getEnumDescById(CardType.class, detail.getPokerType(), "getDesc");
//                detail.setPokerType(desc);
//            }
//        }
        return records;
    }

    @Override
    public Object getRoomDetail(Integer roomId) {
        GongNiuParamDto gongNiuParamDto = gongNiuRoomMapper.selectRoomDetail(roomId);
        GongNiuRoomParamDto niuRoomParamDto = new GongNiuRoomParamDto();
        try {
            CommonUtils.setParam(gongNiuParamDto,niuRoomParamDto);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return niuRoomParamDto;
    }

    @Override
    public Object playGame(RoomIntoReq roomIntoReq, RoomDetail roomDetail, ChannelHandlerContext channelHandlerContext,
                           ConcurrentHashMap<ChannelHandlerContext, ChcRoomInfo> chcRoom,ConcurrentHashMap<ChannelHandlerContext, WaCherInfo> waCher) {
        if (GongNiuAction.type2.getId().equals(roomIntoReq.getAction())){ //准备
            ready(roomIntoReq,roomDetail,channelHandlerContext,chcRoom,waCher);
        }else if (GongNiuAction.type3.getId().equals(roomIntoReq.getAction())){ //开始游戏
            begin(roomIntoReq,roomDetail,channelHandlerContext,chcRoom);
        }else if (GongNiuAction.type6.getId().equals(roomIntoReq.getAction())){ //上庄
//            setAction(chcRoom,channelHandlerContext,GongNiuAction.type6);
            ChcRoomInfo chcRoomInfo = chcRoom.get(channelHandlerContext);
            up(roomIntoReq,roomDetail,chcRoomInfo);
        }else if (GongNiuAction.type7.getId().equals(roomIntoReq.getAction())){ //升庄
            ChcRoomInfo chcRoomInfo = chcRoom.get(channelHandlerContext);
            rise(roomIntoReq,roomDetail,chcRoomInfo);
        }else if (GongNiuAction.type8.getId().equals(roomIntoReq.getAction())){ //下庄
            ChcRoomInfo chcRoomInfo = chcRoom.get(channelHandlerContext);
            xz(roomIntoReq,roomDetail,chcRoomInfo);
        }else if (GongNiuAction.type4.getId().equals(roomIntoReq.getAction())){ //下注
//            setAction(chcRoom,channelHandlerContext,GongNiuAction.type4);
            bets(roomIntoReq,roomDetail);
        }else if (GongNiuAction.type11.getId().equals(roomIntoReq.getAction())){ //亮牌
            brightCard(roomIntoReq,roomDetail,channelHandlerContext);
        }else if (GongNiuAction.type13.getId().equals(roomIntoReq.getAction())){ //退出
            quit(roomIntoReq,roomDetail,channelHandlerContext);
        }else if (GongNiuAction.type18.getId().equals(roomIntoReq.getAction())){
            voice(roomIntoReq,roomDetail);
        }else if (GongNiuAction.type19.getId().equals(roomIntoReq.getAction())){
            interaction(roomIntoReq,roomDetail);
        }else if (GongNiuAction.type997.getId().equals(roomIntoReq.getAction())){
            heartbeat(roomIntoReq,channelHandlerContext);
        }
        return null;
    }

    private void heartbeat(RoomIntoReq roomIntoReq, ChannelHandlerContext channelHandlerContext) {
        channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(roomIntoReq)));
    }

    private void voice(RoomIntoReq roomIntoReq, RoomDetail roomDetail) {
        VoiceResp voiceResp = new VoiceResp();
        voiceResp.setUserId(roomIntoReq.getUserId());
        voiceResp.setVoice(roomIntoReq.getActionValue());
        sendMessageToAll(roomIntoReq,roomDetail,toJsonString(voiceResp),GongNiuAction.type18);
    }

    private void interaction(RoomIntoReq roomIntoReq, RoomDetail roomDetail) {
        JSONObject jsonObject = JSONObject.parseObject(roomIntoReq.getActionValue());
        Integer targetUser = jsonObject.getInteger("targetUser");
        String interaction = jsonObject.getString("interaction");
        InteractionResp interactionResp = new InteractionResp();
        interactionResp.setInteraction(interaction);
        interactionResp.setTargetUser(targetUser);
        interactionResp.setSendUser(roomIntoReq.getUserId());
        sendMessageToAll(roomIntoReq,roomDetail,toJsonString(interactionResp),GongNiuAction.type19);
    }

    @Override
    public Object review(Integer roomId) {
        List<ReviewResp> reviewResp = gongNiuRecordMapper.selectReview(roomId);
        for (ReviewResp resp : reviewResp) {
            List<Poker> pokers = JSONArray.parseArray(resp.getPokerJson(), Poker.class);
            resp.setPoker(pokers);
        }
        return reviewResp;
    }

    @Override
    public void quit(ChcRoomInfo chcRoomInfo, RoomDetail roomDetail, ChannelHandlerContext ctx) {
        RoomIntoReq roomIntoReq = new RoomIntoReq();
        roomIntoReq.setUserId(chcRoomInfo.getUserId());
        roomIntoReq.setRoomId(chcRoomInfo.getRoomId());
        roomIntoReq.setGameType(chcRoomInfo.getType());
        quit2(roomIntoReq,roomDetail,ctx);
    }

    private String getProperty(Object o,String name){
        String s = null;
        try {
            Object property = PropertyUtils.getProperty(o, name);
            if (property!=null){
                s = property.toString();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return s;
    }


    @Override
    public void trusteeship(ChcRoomInfo chcRoomInfo,RoomDetail roomDetail,ConcurrentHashMap<ChannelHandlerContext, ChcRoomInfo> chcRoom) {
        WebSocketClient channelFuture = null;
        JavaWebSocketClient instance = JavaWebSocketFactory.getInstance();
        if (instance!=null){
            channelFuture = instance.connect();
            RoomIntoReq roomIntoReq = new RoomIntoReq();
            roomIntoReq.setAction(RoomAction.type198.getId());
            roomIntoReq.setActionValue(toJsonString(chcRoomInfo));
            roomIntoReq.setUserId(chcRoomInfo.getUserId());
            roomIntoReq.setGameType(chcRoomInfo.getType());
            roomIntoReq.setRoomId(chcRoomInfo.getRoomId());
            channelFuture.send(toJsonString(roomIntoReq));
        }else {
            log.info("为什么没有对象?!");
        }
        roomDetail.getUserTrusteeship().put(chcRoomInfo.getUserId(),channelFuture);
        roomDetail.getUserTrusteeshipThread().put(chcRoomInfo.getUserId(),Thread.currentThread());
        log.info("我进来啦!!!!");
        RoomInfoResp roomInfoResp = new RoomInfoResp();
        roomInfoResp.setGameType(chcRoomInfo.getType());
        roomInfoResp.setRoomId(chcRoomInfo.getRoomId());
        roomInfoResp.setUserId(chcRoomInfo.getUserId());
        Object o = roomDetail.getUserInfo().get(chcRoomInfo.getUserId());
        if (GongNiuAction.type2.getId().equals(getProperty(o,"action"))){ //所有人准备之后立刻退出有可能出现此情况
            RoomIntoReq roomIntoReq = new RoomIntoReq();
            BeanUtils.copyProperties(roomInfoResp,roomIntoReq);
            begin(roomIntoReq,roomDetail,chcRoomInfo.getChannelHandlerContext(),chcRoom);
        }
        if (GongNiuAction.type3.getId().equals(getProperty(o,"action"))){ //上庄完成,选庄阶段
            int round = 1;
            List<SzQueueInfo> szInfo = roomInfoService.getSzInfo(chcRoomInfo.getRoomId(), SzQueueInfo.class);
            if (CollectionUtil.isNotEmpty(szInfo)){
                List<SzQueueInfo> collect = szInfo.stream().filter(a -> "1".equals(a.getBanking())).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(collect)){
                    SzQueueInfo szQueueInfo = collect.get(0);
                    round = szQueueInfo.getRound();
                }
            }
            GongNiuParamDto niuRoomInfo = getNiuRoomInfo(chcRoomInfo.getRoomId());
            BigDecimal bigDecimal = mathMinAnte(round, niuRoomInfo);
            if ("1".equals(chcRoomInfo.getChoice()) && !"1".equals(getProperty(o,"banker"))){  //可选庄玩家
                trusteeshipMessage(roomDetail,roomInfoResp,channelFuture,GongNiuAction.type8,"");
                sleep(500);
                trusteeshipMessage(roomDetail,roomInfoResp,channelFuture,GongNiuAction.type4,bigDecimal.toString());
                sleep(500);
                trusteeshipMessage(roomDetail,roomInfoResp,channelFuture,GongNiuAction.type11,"");
            }else if ("1".equals(getProperty(o,"banker"))){
                sleep(15,channelFuture,roomDetail);
                trusteeshipMessage(roomDetail,roomInfoResp,channelFuture,GongNiuAction.type11,"");
            }else { //普通玩家强退
                sleep(8,channelFuture,roomDetail);
                trusteeshipMessage(roomDetail,roomInfoResp,channelFuture,GongNiuAction.type4,bigDecimal.toString());
                sleep(500);
                trusteeshipMessage(roomDetail,roomInfoResp,channelFuture,GongNiuAction.type11,"");
            }
        }else if (GongNiuAction.type4.getId().equals(getProperty(o,"action"))){ //下注完成,亮牌阶段
            sleep(8,channelFuture,roomDetail);
            trusteeshipMessage(roomDetail,roomInfoResp,channelFuture,GongNiuAction.type11,"");
        }else if (GongNiuAction.type11.getId().equals(getProperty(o,"action"))){
            sleep(8,channelFuture,roomDetail);
            channelFuture.send("");
        }
        RoomIntoReq roomIntoReq = new RoomIntoReq();
        BeanUtils.copyProperties(roomInfoResp,roomIntoReq);
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        quit2(roomIntoReq,roomDetail,chcRoomInfo.getChannelHandlerContext());
        channelFuture.close();
    }

    private void sleep(long time){
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void sleep(int time, WebSocketClient channelFuture,RoomDetail roomDetail){
        try {
            roomDetail.begin(time);
            wait(roomDetail);
            sleep(500);
        } catch (Exception e) {
            e.printStackTrace();
            channelFuture.close();
        }
    }

    @Override
    public void watcherQuit(WaCherInfo waCherInfo, RoomDetail roomDetail, ChannelHandlerContext ctx) {
        RoomIntoReq roomIntoReq = new RoomIntoReq();
        roomIntoReq.setGameType(waCherInfo.getGameType());
        roomIntoReq.setRoomId(waCherInfo.getRoomId());
        roomIntoReq.setUserId(waCherInfo.getUserId());
        quit2(roomIntoReq,roomDetail,ctx);
    }

    private void trusteeshipMessage(RoomDetail roomDetail,RoomInfoResp roomInfoResp,WebSocketClient channelFuture,GongNiuAction niuAction,String actionValue){
        roomInfoResp.setAction(niuAction.getId());
        roomInfoResp.setActionValue(actionValue);
        channelFuture.send(toJsonString(roomInfoResp));
        roomDetail.begin(8);
        wait(roomDetail);
    }

    private void wait(RoomDetail roomDetail) {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        while (roomDetail.getCountDown().getCount()!=0){
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private synchronized void brightCard(RoomIntoReq roomIntoReq, RoomDetail roomDetail, ChannelHandlerContext channelHandlerContext) {
        roomIntoReq.setActionValue("1");
        setProperty(roomIntoReq, roomDetail);
        Collection<GongNiuGameResult> result = roomInfoService.getRoomResult(roomIntoReq.getRoomId(), GongNiuGameResult.class);
        while (CollectionUtil.isEmpty(result) || result.size()!=roomDetail.getUserInfo().size()){
            try {
                log.info("result是{}",result);
                Thread.sleep(500);
                result = roomInfoService.getRoomResult(roomIntoReq.getRoomId(), GongNiuGameResult.class);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        GongNiuGameResult niuGameResult = result.stream().filter(a -> a.getId().equals(roomIntoReq.getUserId())).collect(Collectors.toList()).get(0);
        Object o1 = setProperty(roomIntoReq, roomDetail);
        try {
            PropertyUtils.setProperty(o1,"poker",niuGameResult.getPoker());
        } catch (Exception e) {
            e.printStackTrace();
        }
        GongNiuParamDto niuRoomInfo = getNiuRoomInfo(roomIntoReq.getRoomId());
        GongNiuCardResult niuCardResult = new GongNiuCardResult();
        niuCardResult.setId(roomIntoReq.getUserId());
        niuCardResult.setPoker(niuGameResult.getPoker());
        niuCardResult.setCardType(niuGameResult.getCardType());
        niuCardResult.setCardDesc(CardType.getEnumById(niuGameResult.getCardType()).getDesc());
        niuCardResult.setCardRate(CardUtils.getCardRate(niuRoomInfo.getFlopRule(),niuGameResult.getCardType()));
        sendMessageToAll(roomIntoReq,roomDetail,toJsonString(niuCardResult),GongNiuAction.type11);
        setUserAction(roomIntoReq,roomDetail,GongNiuAction.type11);
        if (MySocketUtil.finish(roomDetail,GongNiuAction.type11.getValue())){
            //所有人亮牌后结算
            roomDetail.interrupt();
            List<CoalitionGongNiuRecord> records = new ArrayList<>();
            for (GongNiuGameResult gameResult : result) {
                Object o = roomDetail.getUserInfo().get(gameResult.getId());
                BigDecimal userRealTime = null;
                if (gameResult.getBanker().equals("0")){
                    userRealTime = gameResult.getCoin();
                }else {
                    userRealTime = gameResult.getAnte();
                }
                if (gameResult.getWin().compareTo(new BigDecimal(0))>0){ //赢
                    //如果赢钱, 抽成
                    BigDecimal percentageRate = roomInfoService.getPercentage();
                    BigDecimal percentageCoin = percentageRate.multiply(gameResult.getWin()).setScale(1, BigDecimal.ROUND_HALF_UP);
                    BigDecimal proxyCoin = new BigDecimal("0");
                    User user = authMapper.selectByPrimaryKey(gameResult.getId());
                    if (user.getProxyRate()!=null&&user.getProxyRate().compareTo(new BigDecimal("0"))>0){
                        proxyCoin = percentageCoin.multiply(new BigDecimal("0.8333")).multiply(user.getProxyRate()).setScale(1, BigDecimal.ROUND_HALF_DOWN);
                    }
                    BigDecimal win = gameResult.getWin().subtract(percentageCoin);
                    userRealTime = userRealTime.add(win);
                    CoalitionPercentage coalitionPercentage = new CoalitionPercentage();
                    coalitionPercentage.setCreateTime(new Date());
                    coalitionPercentage.setGameId(gameResult.getGameId());
                    coalitionPercentage.setPercentageCoin(percentageCoin);
                    coalitionPercentage.setPercentageRate(percentageRate);
                    coalitionPercentage.setPercentageUser(gameResult.getId());
                    coalitionPercentage.setProxyCoin(proxyCoin);
                    percentageMapper.insertUseGeneratedKeys(coalitionPercentage);
                }else {
                    userRealTime = userRealTime.subtract(gameResult.getLose());
                }
                if (userRealTime.compareTo(new BigDecimal(0))<0){
                    userRealTime = new BigDecimal(0);
                }
                List<SzQueueInfo> szInfo = roomInfoService.getSzInfo(roomIntoReq.getRoomId(), SzQueueInfo.class);
                SzQueueInfo bankerInfo = szInfo.stream().filter(a -> a.getBanking().equals("1")).collect(Collectors.toList()).get(0);
                try {
                    for (SzQueueInfo szQueueInfo : szInfo) {
                        if (szQueueInfo.getId().equals(gameResult.getId())){
                            if (gameResult.getBanker().equals("0")){
                                PropertyUtils.setProperty(o,"coin",userRealTime);
                                gameResult.setCoin(userRealTime);
                                szQueueInfo.setCoin(userRealTime);
                                getUserInfoService.changeCoin(gameResult.getId(),userRealTime);
                            }else {
                                szQueueInfo.setRoundNumber(szQueueInfo.getRoundNumber()+1);
                                szQueueInfo.setAnte(userRealTime);
                                gameResult.setAnte(userRealTime);
                                PropertyUtils.setProperty(o,"ante",userRealTime);
                                PropertyUtils.setProperty(o,"round",szQueueInfo.getRound());
                                PropertyUtils.setProperty(o,"roundNumber",szQueueInfo.getRoundNumber()+1);
                            }
                        }
                    }
                    roomInfoService.setSzInfo(roomIntoReq.getRoomId(),szInfo);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                //插入数据库
                CoalitionGongNiuRecord coalitionNiuRecord = new CoalitionGongNiuRecord();
                coalitionNiuRecord.setId(null);
                coalitionNiuRecord.setGameId(gameResult.getGameId());
                coalitionNiuRecord.setCoalitionId(coalitionId);
                coalitionNiuRecord.setRoomId(roomIntoReq.getRoomId());
                coalitionNiuRecord.setUserId(gameResult.getId());
                coalitionNiuRecord.setAnte(bankerInfo.getAnte());
                coalitionNiuRecord.setRound(bankerInfo.getRound());
                coalitionNiuRecord.setRoundNumber(bankerInfo.getRoundNumber());
                coalitionNiuRecord.setBanker(bankerInfo.getId().toString());
                coalitionNiuRecord.setResult(gameResult.getResult());
                coalitionNiuRecord.setPoker(toJsonString(gameResult.getPoker()));
                coalitionNiuRecord.setPokerType(gameResult.getCardType());
                coalitionNiuRecord.setCreateTime(new Date());
                coalitionNiuRecord.setWin(gameResult.getWin());
                coalitionNiuRecord.setLose(gameResult.getLose());
                coalitionNiuRecord.setBets(gameResult.getBets());
                records.add(coalitionNiuRecord);
            }
            gongNiuRecordMapper.insertList(records);
            sendMessageToAll(roomIntoReq,roomDetail,toJsonString(result),GongNiuAction.type12);
            //初始化数据
            init(roomDetail,niuRoomInfo);
            //发送给所有人当前游戏结束
            sendMessageToAll(roomIntoReq,roomDetail,"0",GongNiuAction.type200);
            //如果有玩家金币小于最低入场, 则退出游戏
            Map<Integer, Object> user = new HashMap<>();
            Map<Integer, ChannelHandlerContext> chanel = new HashMap<>();
            Map<Integer, Object> userInfo = roomDetail.getUserInfo();
            Map<Integer, ChannelHandlerContext> userChanel = roomDetail.getUserChanel();
            user.putAll(userInfo);
            chanel.putAll(userChanel);
            for (Map.Entry<Integer,Object> map : user.entrySet()){
                for (Map.Entry<Integer,ChannelHandlerContext> map2 : chanel.entrySet()){
                    if (map.getKey().equals(map2.getKey())){
                        try {
                            Object coin = PropertyUtils.getProperty(map.getValue(), "coin");
                            Object banker = PropertyUtils.getProperty(map.getValue(), "banker");
                            if ("0".equals(banker.toString()) && niuRoomInfo.getIntoCoin().compareTo(new BigDecimal(coin.toString()))>0){ //如果小于最低房间分数,退出房间
                                Thread.sleep(2000);
                                roomIntoReq.setUserId(map.getKey());
                                quit(roomIntoReq,roomDetail,map2.getValue());
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }

        }
    }

    private void init(RoomDetail roomDetail,GongNiuParamDto gongNiuParamDto){
        Map<Integer, Object> userInfo = roomDetail.getUserInfo();
        userInfo.forEach((key,value)->{
            GongNiuRoomUserBaseInfo baseInfo = new GongNiuRoomUserBaseInfo();
            BeanUtils.copyProperties(value,baseInfo);
            baseInfo.setReady(ReadyStatus.type1.getId());
            baseInfo.setBets(null);
            baseInfo.setCover(null);
            baseInfo.setStatus("0");
            baseInfo.setPoker(null);
            userInfo.put(key,baseInfo);
        });
        roomDetail.init(gongNiuParamDto.getAdvancedOptions(),GameType.type2);
        redisTemplate.opsForHash().put(SysConstants.GAME_STATUS,gongNiuParamDto.getId().toString(),GameStatus.type1.getId());
        roomDetail.setStatus(GameStatus.type1.getId());
    }

    private void rise(RoomIntoReq roomIntoReq, RoomDetail roomDetail,ChcRoomInfo chcRoomInfo) {
        Object o = roomDetail.getUserInfo().get(roomIntoReq.getUserId());
        GongNiuParamDto niuRoomInfo = getNiuRoomInfo(roomIntoReq.getRoomId());
        List<SzQueueInfo> szInfo = roomInfoService.getSzInfo(roomIntoReq.getRoomId(), SzQueueInfo.class);
        SzQueueInfo sz = null;
        for (SzQueueInfo szQueueInfo : szInfo) {
            if (roomIntoReq.getUserId().equals(szQueueInfo.getId())){
                BigDecimal coin = szQueueInfo.getAnte().add(szQueueInfo.getCoin());
                switch (szQueueInfo.getRound()){
                    case 1: //一升
                        BigDecimal rise = niuRoomInfo.getFirstBank().multiply(new BigDecimal(2));
                        szQueueInfo.setAnte(rise);
                        szQueueInfo.setCoin(coin.subtract(rise));
                        szQueueInfo.setRoundNumber(1);
                        szQueueInfo.setRound(2);
                        szQueueInfo.setBanking("1");
                        try {
                            PropertyUtils.setProperty(o,"coin",coin.subtract(rise));
                            PropertyUtils.setProperty(o,"ante",rise);
                            PropertyUtils.setProperty(o,"round",2);
                            PropertyUtils.setProperty(o,"roundNumber",1);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        getUserInfoService.changeCoin(roomIntoReq.getUserId(),coin.subtract(rise));break;
                    case 2: //二升
                        BigDecimal rise2 = niuRoomInfo.getFirstBank().multiply(new BigDecimal(4));
                        szQueueInfo.setAnte(rise2);
                        szQueueInfo.setCoin(coin.subtract(rise2));
                        szQueueInfo.setRoundNumber(1);
                        szQueueInfo.setRound(3);
                        szQueueInfo.setBanking("1");
                        try {
                            PropertyUtils.setProperty(o,"coin",coin.subtract(rise2));
                            PropertyUtils.setProperty(o,"ante",rise2);
                            PropertyUtils.setProperty(o,"round",3);
                            PropertyUtils.setProperty(o,"roundNumber",1);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        getUserInfoService.changeCoin(roomIntoReq.getUserId(),coin.subtract(rise2));break;
                }
                sz = szQueueInfo;
            }
        }
        if (chcRoomInfo!=null){
            chcRoomInfo.setChoice(null);
        }
        roomInfoService.setSzInfo(roomIntoReq.getRoomId(),szInfo);
        sendMessageToAll(roomIntoReq,roomDetail,toJsonString(sz),GongNiuAction.type7);
    }

    private synchronized void bets(RoomIntoReq roomIntoReq, RoomDetail roomDetail) {
        Object o = setProperty(roomIntoReq, roomDetail);
        GongNiuRoomUserBaseInfo gongNiuRoomUserBaseInfo = new GongNiuRoomUserBaseInfo();
        BeanUtils.copyProperties(o,gongNiuRoomUserBaseInfo);
        BetsDto betsDto = new BetsDto();
        betsDto.setId(roomIntoReq.getUserId());
        betsDto.setBets(roomIntoReq.getActionValue());
        //如果下注额是锅底的1/3,则发送射门消息
        List<SzQueueInfo> szInfo = roomInfoService.getSzInfo(roomIntoReq.getRoomId(), SzQueueInfo.class);
        SzQueueInfo szQueueInfo = szInfo.stream().filter(a -> a.getBanking().equals("1")).collect(Collectors.toList()).get(0);
        BigDecimal shoot = null;
        if (gongNiuRoomUserBaseInfo.getCoin().compareTo(szQueueInfo.getAnte())>=0){
            shoot = szQueueInfo.getAnte().divide(new BigDecimal(3),0,BigDecimal.ROUND_UP);
        }else {
            shoot = gongNiuRoomUserBaseInfo.getCoin().divide(new BigDecimal(3),0,BigDecimal.ROUND_UP);
        }
        ShootResp shootResp = null;
        if (shoot.compareTo(new BigDecimal(roomIntoReq.getActionValue()))==0){ //射门
            shootResp = new ShootResp(roomIntoReq.getUserId(),shoot,"1");
            sendMessageToAll(roomIntoReq,roomDetail,toJsonString(shootResp),GongNiuAction.type9);
        }else {
            shootResp = new ShootResp(roomIntoReq.getUserId(),new BigDecimal(roomIntoReq.getActionValue()),"0");
            sendMessageToAll(roomIntoReq,roomDetail,toJsonString(shootResp),GongNiuAction.type4);
        }
        setUserAction(roomIntoReq,roomDetail,GongNiuAction.type4);
        if (MySocketUtil.finish(roomDetail,GongNiuAction.type4.getValue())){ //所有人下注完  发牌
            GongNiuParamDto niuRoomInfo = getNiuRoomInfo(roomIntoReq.getRoomId());
            GlobalData globalData = roomDetail.getGlobalData(niuRoomInfo.getAdvancedOptions(),GameType.type2);
            Map<Integer,List<Poker>> usersPoker = new HashMap<>();
            roomDetail.getUserChanel().forEach((key,value)->{
                List<Poker> pokers = new ArrayList<>();
                List<Card> card = globalData.getCard(5);
                log.info("牌库剩余{}张",globalData.getQueue().size());
                for (Card card1 : card) {
                    Poker poker = new Poker(card1.getSuitType(),card1.getFaceType());
                    pokers.add(poker);
                }
                pokers.get(4).setFifth("1");
                roomIntoReq.setUserId(key);
                roomIntoReq.setAction(GongNiuAction.type10.getId());
                roomIntoReq.setActionValue(toJsonString(pokers));
                value.writeAndFlush(new TextWebSocketFrame(toJsonString(roomIntoReq)));
                //存redis
                getUserInfoService.setUserPoker(pokers,key);
                usersPoker.put(key,pokers);
            });
            //把发牌信息给观战者
            roomDetail.getUserChanelWatcher().forEach((key,value)->{
                roomIntoReq.setUserId(key);
                roomIntoReq.setAction(GongNiuAction.type10.getId());
                roomIntoReq.setActionValue(null);
                value.channel().writeAndFlush(new TextWebSocketFrame(toJsonString(roomIntoReq)));
            });
            Integer gameId = roomInfoService.getGameId();
            List<GongNiuGameResult> gongNiuGameResults = new ArrayList<>();
            for (Map.Entry<Integer, Object> map : roomDetail.getUserInfo().entrySet()){
                for (Map.Entry<Integer,List<Poker>> userPoker : usersPoker.entrySet()){
                    if (map.getKey().equals(userPoker.getKey())){
                        GongNiuGameResult gongNiuGameResult = new GongNiuGameResult();
                        BeanUtils.copyProperties(map.getValue(),gongNiuGameResult);
                        gongNiuGameResult.setGameId(gameId);
                        gongNiuGameResult.setPoker(userPoker.getValue());
                        gongNiuGameResults.add(gongNiuGameResult);
                        break;
                    }
                }
            }
            getResult(gongNiuGameResults,roomDetail,niuRoomInfo,szQueueInfo.getAnte()); //计算输赢
            log.info("游戏结果已保存:{}",gongNiuGameResults);
            for (GongNiuGameResult gongNiuGameResult : gongNiuGameResults) {
                gongNiuGameResult.setGameId(gameId);
            }
            //存redis
            roomInfoService.setRoomResult(roomIntoReq.getRoomId(),gongNiuGameResults);
        }

    }

    private BigDecimal mathMinAnte(int round,GongNiuParamDto gongNiuParamDto ){
        int rate = 1;
        if (round==2){
            rate=2;
        }else if (round==3){
            rate=4;
        }
        BigDecimal ante = Ante.getValueById(gongNiuParamDto.getAnte()).multiply(gongNiuParamDto.getFirstBank()).multiply(new BigDecimal(rate)).setScale(0,BigDecimal.ROUND_UP);
        return ante;
    }

    private BigDecimal mathMinBank(int round,GongNiuParamDto gongNiuParamDto ){
        int rate = 1;
        if (round==2){
            rate=2;
        }else if (round==3){
            rate=4;
        }
        BigDecimal ante = new BigDecimal(gongNiuParamDto.getAnte()).multiply(gongNiuParamDto.getFirstBank()).multiply(new BigDecimal(rate));
        return ante;
    }

    private void getResult(List<GongNiuGameResult> list, RoomDetail roomDetail, GongNiuParamDto niuRoomInfo,BigDecimal ante) {
        int type = 1;
        BigDecimal win = new BigDecimal(0);
        BigDecimal lose = new BigDecimal(0);
        GongNiuGameResult bankResult = list.stream().filter(a -> "1".equals(a.getBanker())).collect(Collectors.toList()).get(0);//庄家
        PokerResult bankerCard = CardUtils.getPokerResult(bankResult.getPoker(), roomDetail.getGlobalData(), type,""); //庄家牌型
        try {
            bankResult.setPoker(bankerCard.getPokerList());
            bankResult.setCardType(bankerCard.getCardType().getId());
        } catch (Exception e) {
            log.info("又一个究极报错点:{}",bankerCard);
            e.printStackTrace();
        }
        bankResult.setAnte(ante);
        List<GongNiuGameResult> collect = list.stream().filter(a -> !"1".equals(a.getBanker())).collect(Collectors.toList());//闲家
        for (GongNiuGameResult gameResult : collect) {
            PokerResult playerCard = CardUtils.getPokerResult(gameResult.getPoker(), roomDetail.getGlobalData(), type,"");
            gameResult.setCardType(playerCard.getCardType().getId());
            gameResult.setPoker(playerCard.getPokerList());
            //庄家赢
            if (CardUtils.compareTo(bankerCard,playerCard)>0){
                BigDecimal multiply = gameResult.getBets().multiply(new BigDecimal(CardUtils.getCardRate(niuRoomInfo.getFlopRule(),bankResult.getCardType())));//下注额*庄家牌型倍率
                if (multiply.compareTo(gameResult.getCoin())>0){ //如果大于当前游戏币, 则算游戏币金额
                    multiply = gameResult.getCoin();
                }
                gameResult.setLose(multiply);
                gameResult.setResult(GameResult.type1.getId());
                win = win.add(multiply);
            }
            else { //庄家输
                BigDecimal multiply = gameResult.getBets().multiply(new BigDecimal(CardUtils.getCardRate(niuRoomInfo.getFlopRule(),gameResult.getCardType())));//下注额*庄家加倍率*玩家牌型倍率
                gameResult.setWin(multiply);
                gameResult.setResult(GameResult.type2.getId());
                lose = lose.add(multiply);
            }
        }
        if (win.compareTo(lose)<0 && lose.subtract(win).compareTo(ante)>=0){ //如果庄家输多赢少,并且输的金额大于庄家的底注,则优先发给牌最大的人,直到为0
            BigDecimal rest = ante;
            //排序赢的闲家的牌大小---从大到小
            List<GongNiuGameResult> losePlayer = collect.stream().filter(a -> a.getResult().equals(GameResult.type1.getId())).collect(Collectors.toList());
            List<GongNiuGameResult> winPlayer = collect.stream().filter(a->a.getResult().equals(GameResult.type2.getId())).sorted(new Comparator<GongNiuGameResult>() {
                @Override
                public int compare(GongNiuGameResult o1, GongNiuGameResult o2) {
                    if (o1.getCardType().equals(o2.getCardType())){
                        return CardUtils.compareToSamePoker(o2.getPoker(),o1.getPoker());
                    }else {
                        return Integer.valueOf(o1.getCardType()) - Integer.valueOf(o2.getCardType());
                    }
                }
            }).collect(Collectors.toList());
            for (GongNiuGameResult gameResult : winPlayer) {
                Object o = roomDetail.getUserInfo().get(gameResult.getId());
                GongNiuRoomUserBaseInfo niuRoomUserBaseInfo = new GongNiuRoomUserBaseInfo();
                BeanUtils.copyProperties(o,niuRoomUserBaseInfo);
                if (rest.intValue()==0){
                    gameResult.setWin(new BigDecimal(0));
                    continue;
                }
                if (gameResult.getWin().compareTo(rest)>=0){
                    gameResult.setWin(rest);
                    rest = new BigDecimal(0);
                }else {
                    rest = rest.subtract(gameResult.getWin());
                }
            }
            bankResult.setLose(ante);
            list.clear();
            list.add(bankResult);
            list.addAll(losePlayer);
            list.addAll(winPlayer);
        }else {
            if (win.compareTo(lose)>=0){
                bankResult.setWin(win.subtract(lose));
            }else {
                bankResult.setLose(lose.subtract(win));
            }
            list.clear();
            list.add(bankResult);
            list.addAll(collect);
        }
    }

//    public static void main(String[] args) {
//        List<Poker> list = new ArrayList<>();
//        Poker poker = new Poker("1","11");
//        Poker poker2 = new Poker("2","8");
//        Poker poker3 = new Poker("3","6");
//        Poker poker4 = new Poker("3","7");
//        Poker poker5 = new Poker("1","5");
//        list.add(poker);list.add(poker2);list.add(poker3);list.add(poker4);list.add(poker5);
//        List<Poker> list2 = new ArrayList<>();
//        Poker poker111 = new Poker("2","11");
//        Poker poker222 = new Poker("2","8");
//        Poker poker333 = new Poker("2","7");
//        Poker poker444 = new Poker("4","10");
//        Poker poker555 = new Poker("1","6");
//        list2.add(poker111);list2.add(poker222);list2.add(poker333);list2.add(poker444);list2.add(poker555);
//        List<GongNiuGameResult> winPlayer = new ArrayList<>();
//        GongNiuGameResult gongNiuGameResult = new GongNiuGameResult();
//        gongNiuGameResult.setPoker(list);gongNiuGameResult.setCardType("1");
//        GongNiuGameResult gongNiuGameResult2 = new GongNiuGameResult();
//        gongNiuGameResult2.setPoker(list2);gongNiuGameResult2.setCardType("1");
//        winPlayer.add(gongNiuGameResult);
//        winPlayer.add(gongNiuGameResult2);
//        List<GongNiuGameResult> collect = winPlayer.stream().sorted(new Comparator<GongNiuGameResult>() {
//            @Override
//            public int compare(GongNiuGameResult o1, GongNiuGameResult o2) {
//                if (o1.getCardType().equals(o2.getCardType())) {
//                    return CardUtils.compareToSamePoker(o2.getPoker(), o1.getPoker());
//                } else {
//                    return Integer.valueOf(o1.getCardType()) - Integer.valueOf(o2.getCardType());
//                }
//            }
//        }).collect(Collectors.toList());
//        System.out.println(collect);
//    }

    private void xz(RoomIntoReq roomIntoReq, RoomDetail roomDetail, ChcRoomInfo chcRoomInfo) {
        List<SzQueueInfo> szInfo = roomInfoService.getSzInfo(roomIntoReq.getRoomId(), SzQueueInfo.class);
        SzQueueInfo szQueueInfo = szInfo.stream().filter(a -> a.getId().equals(roomIntoReq.getUserId())).collect(Collectors.toList()).get(0);
        //结算
        if (szQueueInfo.getAnte().intValue()>0){
            BigDecimal add = szQueueInfo.getCoin().add(szQueueInfo.getAnte());
            getUserInfoService.changeCoin(roomIntoReq.getUserId(),add);
            //发送自己的当前信息给所有人
            szQueueInfo.setCoin(add);
            initSzInfo(szQueueInfo);
        }
        sendMessageToAll(roomIntoReq,roomDetail,toJsonString(szQueueInfo),GongNiuAction.type8);
        szInfo.remove(szQueueInfo);
        initSzInfo(szQueueInfo);
        szInfo.add(szQueueInfo);
        Object o = roomDetail.getUserInfo().get(roomIntoReq.getUserId());
        try {
            PropertyUtils.setProperty(o,"banker","0");
            PropertyUtils.setProperty(o,"ante",new BigDecimal(0));
            PropertyUtils.setProperty(o,"round",1);
            PropertyUtils.setProperty(o,"roundNumber",1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        roomInfoService.setSzInfo(roomIntoReq.getRoomId(),szInfo);
        //发送新的上庄玩家给所有人
        GongNiuBeginResp beginResp = new GongNiuBeginResp();
        beginResp.setChoice("1");
        beginResp.setBanker(szInfo.get(0).getId());
        beginResp.setNickName(szInfo.get(0).getNickName());
        sendMessageToAll(roomIntoReq,roomDetail,toJsonString(beginResp),GongNiuAction.type5);
        roomIntoReq.setAction(GongNiuAction.type5.getId());
        roomIntoReq.setActionValue("0");
        setProperty(roomIntoReq,roomDetail);
        if (chcRoomInfo!=null){
            chcRoomInfo.setChoice(null);
        }
    }

    private void up(RoomIntoReq roomIntoReq, RoomDetail roomDetail, ChcRoomInfo chcRoomInfo) {
        roomIntoReq.setAction(GongNiuAction.type5.getId());
        roomIntoReq.setActionValue("1");
        Object o = setProperty(roomIntoReq, roomDetail);
        GongNiuParamDto niuRoomInfo = getNiuRoomInfo(roomIntoReq.getRoomId());
        List<SzQueueInfo> szInfo = roomInfoService.getSzInfo(roomIntoReq.getRoomId(), SzQueueInfo.class);
        SzQueueInfo szQueueInfo = null;
        for (SzQueueInfo queueInfo : szInfo) {
            if (queueInfo.getId().equals(roomIntoReq.getUserId())){
                if (queueInfo.getAnte().intValue()>0){  //如果锅底没用完

                }else {
                    BigDecimal firstBank = niuRoomInfo.getFirstBank();
                    BigDecimal subtract = queueInfo.getCoin().subtract(firstBank);
                    queueInfo.setCoin(subtract);
                    queueInfo.setAnte(firstBank);
                    queueInfo.setBanking("1");
                    try {
                        PropertyUtils.setProperty(o,"coin",subtract);
                        PropertyUtils.setProperty(o,"ante",firstBank);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    getUserInfoService.changeCoin(roomIntoReq.getUserId(),subtract);
                }
                szQueueInfo = queueInfo;
                break;
            }
        }
        roomInfoService.setSzInfo(roomIntoReq.getRoomId(),szInfo);
        if (chcRoomInfo!=null){
            chcRoomInfo.setChoice(null);
        }
        sendMessageToAll(roomIntoReq,roomDetail,toJsonString(szQueueInfo),GongNiuAction.type6);
    }

    private void setUserAction(RoomIntoReq roomIntoReq, RoomDetail roomDetail,GongNiuAction action) {
        Object o = roomDetail.getUserInfo().get(roomIntoReq.getUserId());
        try {
            PropertyUtils.setProperty(o,"action",action.getId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private synchronized void begin(RoomIntoReq roomIntoReq, RoomDetail roomDetail, ChannelHandlerContext channelHandlerContext,ConcurrentHashMap<ChannelHandlerContext, ChcRoomInfo> chcRoom) {
//        chcRoom.put(channelHandlerContext,new ChcRoomInfo(roomIntoReq.getUserId(),roomIntoReq.getRoomId(),roomIntoReq.getGameType(),channelHandlerContext));
        redisTemplate.opsForHash().put(SysConstants.GAME_STATUS,roomIntoReq.getRoomId().toString(),GameStatus.type2.getId());
        redisTemplate.opsForHash().put(SysConstants.GAME_PLAYER_STATUS,roomIntoReq.getUserId().toString(),GameStatus.type2.getId());
        roomDetail.setStatus(GameStatus.type2.getId());
        setUserAction(roomIntoReq,roomDetail,GongNiuAction.type3);
        List<SzQueueInfo> szInfo = roomInfoService.getSzInfo(roomIntoReq.getRoomId(), SzQueueInfo.class);
        GongNiuParamDto niuRoomInfo = getNiuRoomInfo(roomIntoReq.getRoomId());
        GongNiuBeginResp beginResp = new GongNiuBeginResp();
        if (CollectionUtil.isEmpty(szInfo)){ //本房间第一次游戏
            //生成队列
            List<GongNiuRoomUserBaseInfo> userBaseInfo = ObjectUtils.convertList(roomDetail.getUserInfo().values(), GongNiuRoomUserBaseInfo.class);
            List<GongNiuRoomUserBaseInfo> list = userBaseInfo.stream().sorted(Comparator.comparing(GongNiuRoomUserBaseInfo::getSeat)).collect(Collectors.toList());
            List<SzQueueInfo> szQueueInfoList = ObjectUtils.convertList(list, SzQueueInfo.class);
            roomInfoService.setSzInfo(roomIntoReq.getRoomId(),szQueueInfoList);
            //发送给所有人庄家的userId
            beginResp.setBanker(szQueueInfoList.get(0).getId());
            beginResp.setChoice(Choice.type2.getId());
            beginResp.setNickName(szQueueInfoList.get(0).getNickName());
            szInfo= szQueueInfoList;
        }
        List<SzQueueInfo> collect = szInfo.stream().filter(a -> "1".equals(a.getBanking())).collect(Collectors.toList());
        BigDecimal add = new BigDecimal("0");
        Integer userId = null;
        SzQueueInfo szQueueInfo = null;
        if (CollectionUtil.isNotEmpty(collect)){ //如果有正在当庄的玩家
            szQueueInfo = collect.get(0);
            BigDecimal ante = mathMinAnte(szQueueInfo.getRound(), niuRoomInfo);
            BigDecimal bank = mathMinBank(szQueueInfo.getRound()+1, niuRoomInfo);
            if(szQueueInfo.getRoundNumber()>20
                    || (szQueueInfo.getAnte().compareTo(ante)<0 && szQueueInfo.getRound()>=3)
                    || (szQueueInfo.getAnte().compareTo(ante)<0 && szQueueInfo.getCoin().compareTo(bank)<0)){ //局数==20 或者2次升庄 或者分数不够升庄 则下庄
                add = szQueueInfo.getAnte().add(szQueueInfo.getCoin());
                userId = szQueueInfo.getId();
                szQueueInfo.setCoin(add);
                szInfo.remove(szQueueInfo);
                initSzInfo(szQueueInfo);
                szInfo.add(szQueueInfo);
                beginResp.setBanker(szInfo.get(0).getId());
                beginResp.setChoice(Choice.type2.getId());
                beginResp.setNickName(szInfo.get(0).getNickName());
                roomIntoReq.setAction(GongNiuAction.type15.getId());
                roomIntoReq.setActionValue(toJsonString(szQueueInfo));
                channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(toJsonString(roomIntoReq)));
            }else if (szQueueInfo.getAnte().compareTo(ante)<0 && szQueueInfo.getRound()<=2){ //如果低于底注 升庄
                beginResp.setBanker(szQueueInfo.getId());
                beginResp.setChoice(Choice.type3.getId());
                beginResp.setNickName(szQueueInfo.getNickName());
            }else if (szQueueInfo.getRoundNumber()>3){ //如果打了3局 选择上下庄
                beginResp.setBanker(szQueueInfo.getId());
                beginResp.setChoice(Choice.type2.getId());
                beginResp.setNickName(szQueueInfo.getNickName());
            }else {
                beginResp.setBanker(szQueueInfo.getId());
                beginResp.setChoice("0");
                beginResp.setNickName(szQueueInfo.getNickName());
            }
            beginResp.setRound(szQueueInfo.getRound());
            beginResp.setRoundNumber(szQueueInfo.getRoundNumber());
            log.info("当前游戏是:{}轮,{}局",szQueueInfo.getRound(),szQueueInfo.getRoundNumber());
        }else {
            beginResp.setBanker(szInfo.get(0).getId());
            beginResp.setChoice("1");
            beginResp.setNickName(szInfo.get(0).getNickName());
        }
        roomIntoReq.setAction(GongNiuAction.type5.getId());
        roomIntoReq.setActionValue(toJsonString(beginResp));
        channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(toJsonString(roomIntoReq)));
        roomIntoReq.setAction(GongNiuAction.type200.getId());
        roomIntoReq.setActionValue("1");
        setProperty(roomIntoReq,roomDetail);
        if (MySocketUtil.finish(roomDetail,GongNiuAction.type200.getValue())){ //发送所有人开始游戏
            sendMessageToAll(roomIntoReq,roomDetail,GameStatus.type2.getId(),GongNiuAction.type200);
            if (userId!=null){
                getUserInfoService.changeCoin(userId,add);
                Object o = roomDetail.getUserInfo().get(userId);
                try {
                    PropertyUtils.setProperty(o,"banker","0");
                    PropertyUtils.setProperty(o,"coin",add);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            roomInfoService.setSzInfo(roomIntoReq.getRoomId(),szInfo);
            //发送给观战人
            for (Map.Entry<Integer,ChannelHandlerContext> map : roomDetail.getUserChanelWatcher().entrySet()){
                roomIntoReq.setUserId(map.getKey());
                roomIntoReq.setAction(GongNiuAction.type5.getId());
                roomIntoReq.setActionValue(toJsonString(beginResp));
                map.getValue().channel().writeAndFlush(new TextWebSocketFrame(toJsonString(roomIntoReq)));
                roomIntoReq.setAction(GongNiuAction.type15.getId());
                roomIntoReq.setActionValue(toJsonString(szQueueInfo));
                map.getValue().channel().writeAndFlush(new TextWebSocketFrame(toJsonString(roomIntoReq)));
            }
            Collection<ChcRoomInfo> values = chcRoom.values();
            List<ChcRoomInfo> choiceUser = values.stream().filter(a -> a.getUserId().equals(beginResp.getBanker())).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(choiceUser)){
                choiceUser.get(0).setChoice("1");
            }
        }
    }

    private void initSzInfo(SzQueueInfo szQueueInfo){
        szQueueInfo.setBanking("0");
        szQueueInfo.setAnte(new BigDecimal(0));
        szQueueInfo.setRound(1);
        szQueueInfo.setRoundNumber(1);
    }

    private synchronized void ready(RoomIntoReq roomIntoReq, RoomDetail roomDetail, ChannelHandlerContext channelHandlerContext,
                                    ConcurrentHashMap<ChannelHandlerContext, ChcRoomInfo> chcRoom,ConcurrentHashMap<ChannelHandlerContext, WaCherInfo> waCher) {
        waCher.remove(channelHandlerContext);
        chcRoom.put(channelHandlerContext,new ChcRoomInfo(roomIntoReq.getUserId(),roomIntoReq.getRoomId(),roomIntoReq.getGameType(),channelHandlerContext));
        Object o = roomDetail.getUserInfo().get(roomIntoReq.getUserId());
        GongNiuParamDto niuRoomInfo = getNiuRoomInfo(roomIntoReq.getRoomId());
        GongNiuRoomUserBaseInfo gongNiuRoomUserBaseInfo = new GongNiuRoomUserBaseInfo();
        User user = new User();
        user.setId(roomIntoReq.getUserId());
        BigDecimal userRealTime = getUserInfoService.getUserRealTime(user);
        String banker = null;
        try {
            if (o!=null){
                banker = PropertyUtils.getProperty(o,"banker").toString();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (banker==null || "0".equals(banker)){
            if (niuRoomInfo.getIntoCoin().compareTo(userRealTime)>0){
                log.info("金币不足！！！");
                roomIntoReq.setAction(RoomAction.type100.getId());
                roomIntoReq.setAction(RoomAction.type100.getDesc());
                channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(toJsonString(roomIntoReq)));
                throw new RRException("501",RoomAction.type100.getDesc());
            }
        }
        if (o==null){  //第一次准备
            Integer seatNumb = roomInfoService.genSeatNumb(roomIntoReq, roomDetail, niuRoomInfo.getPeopleNumber(),PeopleNumber.class);
            UserVo userByUserId = getUserInfoService.getUserByUserId(roomIntoReq.getUserId());
            gongNiuRoomUserBaseInfo.setCoin(userRealTime);
            gongNiuRoomUserBaseInfo.setId(roomIntoReq.getUserId());
            gongNiuRoomUserBaseInfo.setNickName(userByUserId.getNickName());
            gongNiuRoomUserBaseInfo.setHeadImgUrl(userByUserId.getHeadImgUrl());
            gongNiuRoomUserBaseInfo.setReady(ReadyStatus.type2.getId());
            gongNiuRoomUserBaseInfo.setSeat(seatNumb);

            if (seatNumb==null){
                roomIntoReq.setAction(RoomAction.type101.getId());
                roomIntoReq.setActionValue(RoomAction.type101.getDesc());
                channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(toJsonString(roomIntoReq)));
                throw new RRException("501",RoomAction.type101.getDesc());
            }
            roomDetail.getPlayer().getChannelGroup().add(channelHandlerContext.channel());
            roomDetail.getWatcher().getChannelGroup().remove(channelHandlerContext.channel());
            roomDetail.getUserChanelWatcher().remove(roomIntoReq.getUserId());
            roomDetail.getUserInfo().put(roomIntoReq.getUserId(),gongNiuRoomUserBaseInfo);
            roomDetail.getUserChanel().put(roomIntoReq.getUserId(),channelHandlerContext);
            //发送消息给所有人观战人数
            o = gongNiuRoomUserBaseInfo;
            MySocketUtil.sendWatchCount(roomIntoReq,roomDetail);
        }else { //继续游戏
            BeanUtils.copyProperties(o,gongNiuRoomUserBaseInfo);
            gongNiuRoomUserBaseInfo.setReady(ReadyStatus.type2.getId());
            roomDetail.getUserInfo().put(roomIntoReq.getUserId(),gongNiuRoomUserBaseInfo);
        }
        //发送自己信息给所有人
        sendMessageToAll(roomIntoReq,roomDetail,toJsonString(gongNiuRoomUserBaseInfo), GongNiuAction.type2);
        //判断是否在上庄队列中
        Collection<SzQueueInfo> szInfo = roomInfoService.getSzInfo(roomIntoReq.getRoomId(), SzQueueInfo.class);
        if (CollectionUtil.isNotEmpty(szInfo)&&szInfo.stream().filter(a->a.getId().equals(roomIntoReq.getUserId())).count()==0){ //不在队列中, 则加入队列
            SzQueueInfo szQueueInfo = new SzQueueInfo();
            BeanUtils.copyProperties(o,szQueueInfo);
            szInfo.add(szQueueInfo);
            roomInfoService.setSzInfo(roomIntoReq.getRoomId(),szInfo);
        }
    }

    private void quit(RoomIntoReq roomIntoReq, RoomDetail roomDetail,ChannelHandlerContext channelHandlerContext) {
        CoalitionRoom coalitionRoom = roomMapper.selectByPrimaryKey(roomIntoReq.getRoomId());
        Object o = roomDetail.getUserInfo().get(roomIntoReq.getUserId());
        if ("1".equals(coalitionRoom.getPersonal())){ //私人
            if(roomIntoReq.getUserId().equals(coalitionRoom.getCreateBy())){ //房主无法退出
                roomInfoService.sendErrorMessage(roomIntoReq, RoomAction.type103,channelHandlerContext);
                return ;
            }
        }
        if (GameStatus.type2.getId().equals(roomDetail.getStatus())&&o!=null){ //已开始游戏无法退出游戏
            roomInfoService.sendErrorMessage(roomIntoReq,RoomAction.type199,channelHandlerContext);
            return;
        }
        if (o!=null){
            try {
                Object banker = PropertyUtils.getProperty(o, "banker");
                List<SzQueueInfo> szInfo = roomInfoService.getSzInfo(roomIntoReq.getRoomId(), SzQueueInfo.class);
                List<SzQueueInfo> collect = szInfo.stream().filter(a -> "1".equals(a.getBanking())).collect(Collectors.toList());
                if ("1".equals(banker.toString())&&GameStatus.type1.getId().equals(roomDetail.getStatus())&&
                        CollectionUtil.isNotEmpty(collect)&&collect.get(0).getRoundNumber()<4){ //如果是庄家,切局数少于3
                    roomInfoService.sendErrorMessage(roomIntoReq, RoomAction.type105,channelHandlerContext);
                    return ;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //发送给所有人XX退出了房间
        quit2(roomIntoReq, roomDetail, channelHandlerContext);
    }

    private void quit2(RoomIntoReq roomIntoReq, RoomDetail roomDetail, ChannelHandlerContext channelHandlerContext) {
        if (roomDetail.getUserInfo().get(roomIntoReq.getUserId())!=null){ //玩家
            sendMessageToAll(roomIntoReq,roomDetail,String.valueOf(roomIntoReq.getUserId()), GongNiuAction.type13);
            roomInfoService.quit(roomIntoReq,roomDetail,channelHandlerContext);
            //清除上庄信息
            List<SzQueueInfo> szInfo = roomInfoService.getSzInfo(roomIntoReq.getRoomId(), SzQueueInfo.class);
            if (CollectionUtil.isNotEmpty(szInfo)){
                List<SzQueueInfo> collect = szInfo.stream().filter(a -> a.getId().equals(roomIntoReq.getUserId())).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(collect)){
                    SzQueueInfo szQueueInfo = collect.get(0);
                    if (szQueueInfo.getBanking().equals("1")){
                        BigDecimal add = szQueueInfo.getCoin().add(szQueueInfo.getAnte());
                        getUserInfoService.changeCoin(szQueueInfo.getId(),add);
                    }
                    szInfo.remove(collect.get(0));
                    roomInfoService.setSzInfo(roomIntoReq.getRoomId(),szInfo);
                    if(CollectionUtil.isEmpty(szInfo)){
                        roomDetail.setStatus(GameStatus.type1.getId());
                    }
                }
                if (szInfo.size()==1 && "1".equals(szInfo.get(0).getBanking())){ //如果房间里只剩下庄家. 则结算
                    SzQueueInfo szQueueInfo = szInfo.get(0);
                    BigDecimal coin = szQueueInfo.getCoin();
                    coin = szQueueInfo.getAnte().add(coin);
                    getUserInfoService.changeCoin(szQueueInfo.getId(),coin);
                    szQueueInfo.setCoin(coin);
                    initSzInfo(szQueueInfo);
                    Object o = roomDetail.getUserInfo().get(szQueueInfo.getId());
                    try {
                        PropertyUtils.setProperty(o,"banker","0");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    roomDetail.setStatus(GameStatus.type1.getId());
                    roomInfoService.setSzInfo(roomIntoReq.getRoomId(),szInfo);
                    sendMessageToAll(roomIntoReq,roomDetail,toJsonString(szQueueInfo),GongNiuAction.type14);
                }
            }
            roomInfoService.deleteRoomResult(roomIntoReq.getRoomId(),roomIntoReq.getUserId(),GongNiuGameResult.class);
            getUserInfoService.deleteUserPoker(roomIntoReq.getUserId());
            redisTemplate.opsForHash().delete(SysConstants.GAME_PLAYER_STATUS,roomIntoReq.getUserId().toString());
        }else { //观战
            //发送给所有人观战人数
            roomInfoService.quit(roomIntoReq,roomDetail,channelHandlerContext);
            roomIntoReq.setActionValue(String.valueOf(roomIntoReq.getUserId()));
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(toJsonString(roomIntoReq)));
            MySocketUtil.sendWatchCount(roomIntoReq,roomDetail);
        }
        channelHandlerContext.close();
    }

    private GongNiuParamDto getNiuRoomInfo(Integer roomId){
        String roomDetail = roomInfoService.getRoomDetail(roomId, GameType.type1.getId());
        GongNiuParamDto niuNiuParamDto = null;
        if (!StringUtils.isEmpty(roomDetail)){
            niuNiuParamDto = JSONObject.parseObject(roomDetail, GongNiuParamDto.class);
        }else {
            niuNiuParamDto = gongNiuRoomMapper.selectRoomDetail(roomId);
            roomInfoService.setRoomDetail(niuNiuParamDto);
        }
        return niuNiuParamDto;
    }

    private void sendMessageToAll(RoomIntoReq roomIntoReq,RoomDetail roomDetail,String message,GongNiuAction gongNiuAction){
        RoomInfoResp roomInfoResp = new RoomInfoResp();
        BeanUtils.copyProperties(roomIntoReq,roomInfoResp);
        if (gongNiuAction!=null){
            roomInfoResp.setAction(gongNiuAction.getId());
        }
        roomInfoService.sendChanel(roomDetail, message, roomInfoResp);
    }

    private Object setProperty(RoomIntoReq roomIntoReq, RoomDetail roomDetail){
        Object o = roomDetail.getUserInfo().get(roomIntoReq.getUserId());
        String str = CommonUtils.getEnumDescById(GongNiuAction.class, roomIntoReq.getAction(), "getValue");
        try {
            if (!StringUtils.isEmpty(roomIntoReq.getActionValue())){
                PropertyUtils.setProperty(o,str,CommonUtils.convert(PropertyUtils.getPropertyType(o,str),roomIntoReq.getActionValue()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return o;
    }
}
